package com.blacktech.dbu.meta.controller;

import com.blacktech.dbu.core.annotation.IgnoreResponseWrap;
import com.blacktech.dbu.core.dict.DatabaseDialect;
import com.blacktech.dbu.meta.entity.DbuSchema;
import com.blacktech.dbu.meta.entity.DbuTable;
import com.blacktech.dbu.meta.service.TemplateDDLScriptService;
import freemarker.template.TemplateException;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

/**
 * DDL脚本导出控制器
 *
 * @author yanyunsong
 */
@RestController
@RequestMapping("/api/metadata/ddl")
@Tag(name = "DDL脚本导出", description = "DDL脚本导出相关接口")
public class DDLScriptController {

    @Autowired
    private TemplateDDLScriptService templateDDLScriptService;

    /**
     * 导出单表DDL脚本(基于模板引擎)
     * @param table 数据表
     * @param schemaName 数据库模式名称
     * @param dbType 数据库类型
     * @return DDL脚本文件
     */
    @PostMapping("/table/{schemaName}/{dbType}")
    @Operation(summary = "导出单表DDL脚本", description = "基于模板引擎导出指定表的DDL脚本")
    @IgnoreResponseWrap(reason = "DDL文件下载需要原始响应")
    public ResponseEntity<ByteArrayResource> exportTableDDL(@RequestBody DbuTable table,
                                                         @PathVariable String schemaName,
                                                         @PathVariable String dbType) {
        try {
            // 创建一个临时的DbuSchema对象用于生成DDL
            DbuSchema schema = new DbuSchema();
            schema.setSchemaName(schemaName);

            // 根据dbType设置schema的dbType属性
            DatabaseDialect dialect = parseDatabaseType(dbType);
            schema.setDbType(dialect);

            // 生成DDL脚本
            String ddlScript = switch (dialect) {
                case mysql -> templateDDLScriptService.generateMySQLTableDDL(table, schema);
                case oracle -> templateDDLScriptService.generateOracleTableDDL(table, schema);
                case postgresql -> templateDDLScriptService.generateMySQLTableDDL(table, schema); // 暂时使用MySQL模板
                case oceanBase_mysql -> templateDDLScriptService.generateMySQLTableDDL(table, schema); // 使用MySQL模板
                case oceanBase_oracle -> templateDDLScriptService.generateOracleTableDDL(table, schema); // 使用Oracle模板
                default -> templateDDLScriptService.generateMySQLTableDDL(table, schema);
            };

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            String filename = "ddl-" + schemaName + "-" + table.getTableName() + ".sql";
            headers.setContentDispositionFormData("attachment",
                    URLEncoder.encode(filename, StandardCharsets.UTF_8));

            // 创建资源对象
            ByteArrayResource resource = new ByteArrayResource(ddlScript.getBytes(StandardCharsets.UTF_8));

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);

        } catch (IOException | TemplateException e) {
            // 错误情况下返回错误信息
            String errorMessage = "Error generating DDL script: " + e.getMessage();
            ByteArrayResource errorResource = new ByteArrayResource(errorMessage.getBytes(StandardCharsets.UTF_8));

            return ResponseEntity.status(500)
                    .contentType(MediaType.TEXT_PLAIN)
                    .body(errorResource);
        }
    }

    /**
     * 导出数据库模式DDL脚本(基于模板引擎)
     * @param schema 数据库模式
     * @return DDL脚本文件
     */
    @PostMapping("/schema")
    @Operation(summary = "导出数据库模式DDL脚本", description = "基于模板引擎导出整个数据库模式的DDL脚本")
    @IgnoreResponseWrap(reason = "DDL文件下载需要原始响应")
    public ResponseEntity<ByteArrayResource> exportSchemaDDL(@RequestBody DbuSchema schema) {
        try {
            String ddlScript = templateDDLScriptService.generateSchemaDDL(schema);

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            String filename = "ddl_" + schema.getSchemaName() + ".sql";
            headers.setContentDispositionFormData("attachment",
                    URLEncoder.encode(filename, StandardCharsets.UTF_8));

            // 创建资源对象
            ByteArrayResource resource = new ByteArrayResource(ddlScript.getBytes(StandardCharsets.UTF_8));

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);

        } catch (IOException | TemplateException e) {
            // 错误情况下返回错误信息
            String errorMessage = "Error generating DDL script: " + e.getMessage();
            ByteArrayResource errorResource = new ByteArrayResource(errorMessage.getBytes(StandardCharsets.UTF_8));

            return ResponseEntity.status(500)
                    .contentType(MediaType.TEXT_PLAIN)
                    .body(errorResource);
        }
    }

    /**
     * 获取支持的数据库类型列表
     */
    @GetMapping("/database-types")
    @Operation(summary = "获取支持的数据库类型", description = "获取系统支持的数据库类型列表")
    public DatabaseTypeInfo[] getSupportedDatabaseTypes() {
        return Arrays.stream(DatabaseDialect.values())
                .map(dialect -> new DatabaseTypeInfo(
                        dialect.name(),
                        getDisplayName(dialect),
                        getDescription(dialect)
                ))
                .toArray(DatabaseTypeInfo[]::new);
    }

    private String getDisplayName(DatabaseDialect dialect) {
        return switch (dialect) {
            case mysql -> "MySQL";
            case oracle -> "Oracle";
            case postgresql -> "PostgreSQL";
            case oceanBase_mysql -> "OceanBase (MySQL模式)";
            case oceanBase_oracle -> "OceanBase (Oracle模式)";
        };
    }

    private String getDescription(DatabaseDialect dialect) {
        return switch (dialect) {
            case mysql -> "MySQL数据库";
            case oracle -> "Oracle数据库";
            case postgresql -> "PostgreSQL数据库";
            case oceanBase_mysql -> "OceanBase数据库（MySQL兼容模式）";
            case oceanBase_oracle -> "OceanBase数据库（Oracle兼容模式）";
        };
    }

    /**
     * 解析数据库类型字符串
     */
    private DatabaseDialect parseDatabaseType(String dbType) {
        if (dbType == null) {
            return DatabaseDialect.mysql;
        }

        return switch (dbType.toLowerCase()) {
            case "mysql", "mysql8" -> DatabaseDialect.mysql;
            case "oracle", "oracle11g", "oracle12c" -> DatabaseDialect.oracle;
            case "postgresql", "postgres" -> DatabaseDialect.postgresql;
            case "oceanbase", "oceanbase_mysql" -> DatabaseDialect.oceanBase_mysql;
            default -> DatabaseDialect.mysql;
        };
    }

    /**
     * 数据库类型信息
     */
    public record DatabaseTypeInfo(String code, String displayName, String description) {}
}